/*!
 * \file cics_header.c
 *
 * \brief 消息头操作
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.
 *
 * \version 1.0
 * \author songbb
 * \date 2015/10/07
 *
 */

#include <stdio.h>
#include <netinet/in.h>
#include <frct_comm.h>

#include "cics_comm.h"
#include "cics_core.h"

#define APM_CICS_HEADER_MAGIC 0x47617465            //Gate

int cics_header_detect(char *p_payload
                    , unsigned int ui_payload_len)
{
    unsigned int *p_ui_magic;
    unsigned int ui_magic;

    if (ui_payload_len < APM_CICS_PKT_HEADER_LEN)
        goto unknown;

    p_ui_magic = (unsigned int *) p_payload;
    ui_magic = (unsigned int) ntohl(*p_ui_magic);

    if (ui_magic != APM_CICS_HEADER_MAGIC)
        goto unknown;

    return APM_L7_IS_YES;
unknown:
    return APM_L7_IS_UNKNOWN;
}

int cics_header_unpack(char *p_payload
                    , unsigned int ui_payload_len
                    , Cics_header *p_st_cics_header)
{
    unsigned int *p_ui_magic;
    unsigned int ui_magic;
    unsigned int *p_ui_flow_version;
    unsigned int *p_ui_flow_type;
    unsigned int *p_ui_msg_id;
    int *p_i_gateway_rc;
    unsigned int *p_ui_request_type_len;
    unsigned int ui_request_type_len;
    unsigned int *p_ui_data_which_follows;
    unsigned int ui_offset = 0;

    if (ui_payload_len < APM_CICS_PKT_HEADER_LEN)
        goto error;

    p_ui_magic = (unsigned int *) p_payload;
    ui_magic = (unsigned int) ntohl(*p_ui_magic);

    if (ui_magic != APM_CICS_HEADER_MAGIC)
        goto error;

    p_ui_flow_version = (unsigned int *)(p_payload + 4);
    p_st_cics_header->ui_flow_version = (unsigned int) ntohl(*p_ui_flow_version);

    p_ui_flow_type = (unsigned int *)(p_payload + 8);
    p_st_cics_header->ui_flow_type = (unsigned int) ntohl(*p_ui_flow_type);

    p_ui_msg_id = (unsigned int *)(p_payload + 12);
    p_st_cics_header->ui_msg_id = (unsigned int) ntohl(*p_ui_msg_id);

    p_i_gateway_rc = (int *)(p_payload + 16);
    p_st_cics_header->i_gateway_rc = (int) ntohl(*p_i_gateway_rc);

    if (p_st_cics_header->ui_flow_version == APM_CICS_GATEWAY_FLOW_V100)
    {
        memcpy(p_st_cics_header->arr_req_type, p_payload + 20, 4);
        ui_offset += 24;
    }
    else
    {
        p_ui_request_type_len = (unsigned int *)(p_payload + 20);
        ui_request_type_len = (unsigned int) ntohl(*p_ui_request_type_len);
        if (ui_request_type_len < APM_CICS_REQ_TYPE_MAXLEN)
            memcpy(p_st_cics_header->arr_req_type, p_payload + 24, ui_request_type_len);
        ui_offset += 24 + ui_request_type_len;
    }

    if (p_st_cics_header->ui_flow_version >= APM_CICS_GATEWAY_FLOW_V200)
        ui_offset += 1;

    p_ui_data_which_follows = (unsigned int *)(p_payload + ui_offset);
    p_st_cics_header->ui_data_which_follows = (unsigned int) ntohl(*p_ui_data_which_follows);

    p_st_cics_header->ui_header_len = ui_offset + 4;

    return FR_SUCC;
error:
    return FR_FAIL;
}
